package com.sentrix.auto.printercenter.common;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
public class QRCodeUtil {
    // 1. 固定子目录（项目根目录下的qrcode文件夹）
    private static final String QR_SUB_DIR = "qrcode";
    // 2. 二维码默认参数
    // 二维码参数
    private static final int QR_WIDTH = 300; // 二维码宽度
    private static final int QR_HEIGHT = 300; // 二维码高度
    private static final String FORMAT = "png"; // 图片格式
    private static final int TEXT_AREA_HEIGHT = 100; // 文字区域高度
    private static final String CHARSET = "UTF-8"; // 字符集
    // 3. 时间戳格式（生成唯一文件名，避免覆盖）
    private static final SimpleDateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    public static String generateQRCodeBase64(String content, Integer width, Integer height, String printerName, String printerCode) {
        BufferedImage image = null;
        try {
            image = generateQRCode(content, width, height, printerName, printerCode);
        } catch (WriterException e) {
            log.error("generate QR Code error:{}", e.getMessage());
            throw new RuntimeException("generate QR Code error");
        }
        // 转换为Base64
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(image, FORMAT, baos);
            byte[] imageBytes = baos.toByteArray();
            //return cn.hutool.core.codec.Base64.encode(imageBytes);
            return Base64.getEncoder().encodeToString(imageBytes);
//            return "data:image/" + FORMAT + ";base64," + Base64.getEncoder().encodeToString(imageBytes);
        }catch (IOException e){
            log.error("QR Code to Base64 error:{}", e.getMessage());
            throw new RuntimeException("QR Code to Base64 error");
        }
    }


    /**
     * 生成带文字的二维码（下方包含PrinterName和PrinterCode）
     *
     * @param content     二维码内容（如URL）
     * @param printerName 打印机名称
     * @param printerCode 打印机编码
     * @return 保存到当前目录的完整路径
     * @throws WriterException 编码异常
     * @throws IOException     IO异常
     */
    public static BufferedImage generateQRCode(String content, Integer width, Integer height, String printerName, String printerCode)
            throws WriterException {
        // 1. 生成二维码矩阵
        BitMatrix bitMatrix = generateQRCodeMatrix(content, width, height);

        // 2. 创建复合画布（宽度=二维码宽度，高度=二维码高度+文字区域高度）
        int totalHeight = bitMatrix.getHeight() + TEXT_AREA_HEIGHT;
        BufferedImage combinedImage = new BufferedImage(bitMatrix.getWidth(), totalHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = combinedImage.createGraphics();

        // 3. 填充白色背景
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, bitMatrix.getWidth(), totalHeight);

        // 4. 绘制二维码（到画布上方）
        drawQRCodeToImage(bitMatrix, combinedImage);

        // 5. 绘制文字（到画布下方）
        drawTextToImage(bitMatrix.getWidth(), bitMatrix.getHeight(), printerName, printerCode, g2d);

        // 6. 释放资源
        g2d.dispose();

        return combinedImage;
    }

    private static void drawTextToImage(int qrWidth, int qrHeight, String printerName, String printerCode, Graphics2D g2d) {
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("SimSun", Font.PLAIN, 16));
        FontMetrics fontMetrics = g2d.getFontMetrics();

        // 文字起始Y坐标（二维码高度 + 文字区域内边距）
        int startY = qrHeight + 30; // 距离二维码底部30像素

        // 绘制第一行：PrinterName
        String line1 = "PrinterName: " + (StringUtils.isNotBlank(printerName) ? printerName : "");
        int line1Width = fontMetrics.stringWidth(line1);
        int line1X = (qrWidth - line1Width) / 2;// 水平居中
        g2d.drawString(line1, line1X, startY);

        // 绘制第二行：PrinterCode（距离第一行30像素）
        String line2 = "PrinterCode: " + (StringUtils.isNotBlank(printerCode) ? printerCode : "");
        int line2Width = fontMetrics.stringWidth(line2);
        int line2X = (qrWidth - line2Width) / 2;
        g2d.drawString(line2, line2X, startY + 30);
    }

    private static void drawQRCodeToImage(BitMatrix bitMatrix, BufferedImage combinedImage) {
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                Color color = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE;
                combinedImage.setRGB(x, y, color.getRGB());
            }
        }
    }

    /**
     * 基础二维码生成逻辑（复用）
     */
    private static void generateQRCodeToFile(String content, Integer width, Integer height,
                                             String fullFilePath, String format) throws WriterException, IOException {
        BitMatrix matrix = generateQRCodeMatrix(content, width, height);
        Path path = new File(fullFilePath).toPath();
        MatrixToImageWriter.writeToPath(matrix, format, path);
    }

    public static BufferedImage generateQRCodeToBytes(String content, int width, int height, String format)
            throws WriterException {
        BitMatrix bitMatrix = generateQRCodeMatrix(content, width, height);
        return MatrixToImageWriter.toBufferedImage(bitMatrix);
    }

    /**
     * 生成二维码矩阵（ZXing核心逻辑）
     */
    private static BitMatrix generateQRCodeMatrix(String content, Integer width, Integer height) throws WriterException {
        // 参数校验
        if (StringUtils.isBlank(content)) {
            throw new IllegalArgumentException("二维码内容不能为空");
        }
        if ((Objects.nonNull(width) && width <= 0) || (Objects.nonNull(height) && height <= 0)) {
            throw new IllegalArgumentException("宽度/高度必须为正数");
        }
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); // 15%容错
        hints.put(EncodeHintType.MARGIN, 1); // 窄边距
        QRCodeWriter writer = new QRCodeWriter();
        return writer.encode(content, BarcodeFormat.QR_CODE, Objects.isNull(width) ? QR_WIDTH : width, Objects.isNull(height) ? QR_HEIGHT : height, hints);
    }


    public static void main(String[] args) throws Exception {
        String baseCode = generateQRCodeBase64("https://www.baidu.com", 300, 300, "PrinterName", "PrinterCode");
        System.out.println(baseCode);
    }
}
